package edu.aynu.service.impl;

import edu.aynu.dao.*;
import edu.aynu.entity.*;
import edu.aynu.service.ExamService;
import edu.aynu.util.InvitationCodeUtil;
import edu.aynu.util.ProblemUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * (Exam)表服务实现类
 *
 * @author sitong
 * @date 2021-06-21 20:50:40
 */
@Service("examService")
public class ExamServiceImpl implements ExamService {
    @Resource
    private ExamDao examDao;

    @Resource
    private ProblemDao problemDao;

    @Resource
    private ExamItemDao examItemDao;

    @Resource
    private ProblemExamDao problemExamDao;

    @Resource
    private UserDao userDao;

    @Resource
    private GroupDao groupDao;

    @Resource
    private AnswerDao answerDao;


    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public Exam queryById(Integer id) {
        ExamItem examItem = new ExamItem();
        examItem.setExamId(id);
        // 获取考试选项表
        List<ExamItem> examItems = this.examItemDao.queryAll(examItem);
        // 获取选项对应的题目
        for (ExamItem item : examItems) {
            ProblemExam problemExam = new ProblemExam();
            problemExam.setExamItemId(item.getId());
            List<ProblemExam> problemExams = this.problemExamDao.queryAll(problemExam);

            List<Problem> problemList = new ArrayList<>();
            for (ProblemExam exam : problemExams) {
                Problem problem = this.problemDao.queryById(exam.getProblemId());
                problem.setAnswer(null);
                problemList.add(problem);
            }
            item.setProblemList(problemList);
        }
        // 查询对应的考试信息
        Exam exam = this.examDao.queryById(id);
        exam.setExamItemList(examItems);
        return exam;
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<Exam> queryAllByLimit(int offset, int limit) {
        return this.examDao.queryAllByLimit(offset, limit);
    }

    /**
     * 通过实体作为筛选条件查询
     *
     * @param exam 实例对象
     * @return 对象列表
     */
    @Override
    public List<Exam> queryAll(Exam exam) {
        return this.examDao.queryAll(exam);
    }

    /**
     * 新增数据
     *
     * @param exam 实例对象
     * @return 实例对象
     */
    @Override
    public String insert(Exam exam) {
        int examRow = 0, examItemRow = 0, problemExamRow = 0, updateRow = 0,
                groupRow = 0, totalscore = 0;
        // 设置考试时长
        exam.setDuration((exam.getEndTime().getTime() - exam.getStartTime().getTime())/1000);
        // 判断考试状态
        Date nowDate = new Date();
        if(nowDate.getTime() < exam.getStartTime().getTime()) {
            exam.setStatus("未开始");
        } else if(nowDate.getTime() > exam.getStartTime().getTime()
                && nowDate.getTime() < exam.getEndTime().getTime()) {
            exam.setStatus("进行中");
        } else if(nowDate.getTime() > exam.getEndTime().getTime()){
            exam.setStatus("已结束");
        }
        // 设置邀请码
        exam.setInvitationCode(InvitationCodeUtil.getUUID());
        examRow = this.examDao.insert(exam);

        for (ExamItem examItem : exam.getExamItemList()) {
            totalscore += examItem.getNum() * examItem.getScore();
            // 向examitem表插入数据
            examItem.setExamId(exam.getId());
            examItemRow = this.examItemDao.insert(examItem);
            // 随机抽题,如果题库的题目数量少于需要的数量，则改变需要的数量
            int problemNum = this.problemDao.selectCountByType(examItem.getType(), exam.getCourseName());
            if(problemNum < examItem.getNum()) {
                examItem.setNum(problemNum);
                this.examItemDao.update(examItem);
            }
            List<Problem> problems = this.problemDao.extract(exam.getCourseName(), examItem);
            // 向problemexam中间表插入数据
            ProblemExam problemExam = new ProblemExam();
            for (Problem problem : problems) {
                problemExam.setExamItemId(examItem.getId());
                problemExam.setProblemId(problem.getId());
                problemExamRow = this.problemExamDao.insert(problemExam);
            }
        }

        // 更新exam表中totalscore
        exam.setTotalScore(totalscore);
        updateRow = this.examDao.update(exam);

        // 向group表添加数据
//        Group group = new Group();
//        group.setExamId(exam.getId());
//        group.setAddTime(new Date());
//        group.setIsCommit(false);
//        User user = new User();
//        user.setUsername(exam.getOwnerNickname());
//        group.setUserId(this.userDao.queryOne(user).getId());
//        groupRow = this.groupDao.insert(group);


        if(examRow > 0 && examItemRow > 0 && problemExamRow > 0 && updateRow > 0) {
            return exam.getInvitationCode();
        }
        return null;
    }

    /**
     * 修改数据
     *
     * @param exam 实例对象
     * @return 实例对象
     */
    @Override
    public int update(Exam exam) {
        return this.examDao.update(exam);
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        return this.examDao.deleteById(id) > 0;
    }

    /**
     * 批改试卷
     * @param examAnswer
     * @return
     */
    @Override
    public int correctExam(ExamAnswer examAnswer) {
        Group group = new Group();
        group.setExamId(examAnswer.getExamId());
        group.setUserId(examAnswer.getUserId());
        if(this.groupDao.queryAll(group).get(0).getIsCommit()) {
            return -1;
        }

        int totalScore = 0;

        ExamItem examItem = new ExamItem();
        examItem.setExamId(examAnswer.getExamId());
        List<ExamItem> examItems = this.examItemDao.queryAll(examItem);
        // 获取考试卷
        for (ExamItem item : examItems) {
            ProblemExam problemExam = new ProblemExam();
            problemExam.setExamItemId(item.getId());
            // 获取考试题
            List<Problem> problemList = new ArrayList<>();
            List<ProblemExam> problemExams = this.problemExamDao.queryAll(problemExam);
            for (ProblemExam exam : problemExams) {
                problemList.add(this.problemDao.queryById(exam.getProblemId()));
            }
            // 批卷给分
            if(ProblemUtil.CHOICE.equals(item.getType())) {
                totalScore += titleIsTrue(problemList, examAnswer.getChoice(), examAnswer.getUserId(),
                        examAnswer.getExamId(), item.getScore());
            }
            if(ProblemUtil.CLOZE.equals(item.getType())) {
                totalScore += titleIsTrue(problemList, examAnswer.getCloze(), examAnswer.getUserId(),
                        examAnswer.getExamId(), item.getScore());
            }
            if(ProblemUtil.JUDGE.equals(item.getType())) {
                totalScore += titleIsTrue(problemList, examAnswer.getJudge(), examAnswer.getUserId(),
                        examAnswer.getExamId(), item.getScore());
            }
            if(ProblemUtil.MULTIPLE_CHOICE.equals(item.getType())) {
                totalScore += titleIsTrue(problemList, examAnswer.getMultipleChoice(),
                        examAnswer.getUserId(), examAnswer.getExamId(), item.getScore());
            }
        }


        group.setId(this.groupDao.queryAll(group).get(0).getId());
        group.setScore(totalScore);
        group.setIsCommit(true);
        this.groupDao.update(group);

        return totalScore;
    }

    /**
     * 判断每种类型的题目是否正确
     * @param problems
     * @param examAnswer
     * @param userId
     * @param examId
     * @param score
     * @return
     */
    public int titleIsTrue(List<Problem> problems, List<String> examAnswer, int userId, int examId, int score) {
        List<Answer> answers = new ArrayList<>();

        boolean isCorrect ;  // 是否正确
        int totalScore = 0;  //总分

        for(int i = 0; i < problems.size(); i++) {
            isCorrect = false;
            Answer answer = new Answer();
            answer.setExamId(examId);
            answer.setUserId(userId);

            // 用户答案和正确答案去空
            answer.setTrueAnswer(problems.get(i).getAnswer().trim());
            answer.setProblemId(problems.get(i).getId());
            answer.setScore(0);
            if(examAnswer.get(i) != null) {
                answer.setUserAnswer(examAnswer.get(i).trim());
                // 判断答题是否正确
                if(ProblemUtil.CLOZE.equals(problems.get(i).getType())) {
                    // 填空题可能存在多个答案
                    String[] userAnswers = answer.getUserAnswer().split("#");
                    boolean flag = true;  // 判断是否正确
                    for (String userAnswer : userAnswers) {
                        if(!answer.getTrueAnswer().contains(userAnswer)) {
                            flag = false;
                            break;
                        }
                    }
                    if(flag) {
                        isCorrect = true;
                        totalScore += score;
                        answer.setScore(score);
                    } else {
                        isCorrect = false;
                        answer.setScore(0);
                    }
                } else {
                    if(answer.getTrueAnswer().equals(answer.getUserAnswer())) {
                        isCorrect = true;
                        totalScore += score;
                        answer.setScore(score);
                    }
                }
            }

            answer.setIsCorrect(isCorrect);
            answers.add(answer);
        }

        this.answerDao.insertBatch(answers);
        return totalScore;
    }

    /**
     * 通过邀请码添加试卷
     * @param invitationCode
     * @param userId
     * @return
     */
    @Override
    public int insertByInvitationCode(String invitationCode, Integer userId) {
        Group group = new Group();
        Exam exam = new Exam();

        // 通过邀请码获取examId
        exam.setInvitationCode(invitationCode);
        group.setExamId(this.examDao.queryAll(exam).get(0).getId());

        // 查询这个用户是否已经存在这张试卷
        List<Group> groups = this.groupDao.queryAll(group);
        for (Group tempGroup : groups) {
            if(userId != null && userId == tempGroup.getUserId()) {
                return -1;
            }
        }

        // 向group表插入数据
        group.setUserId(userId);
        group.setAddTime(new Date());
        group.setScore(0);
        group.setIsCommit(false);
        return this.groupDao.insert(group);
    }

    /**
     * 通过userId获取考试列表
     * @param userId
     * @return
     */
    @Override
    public List<Exam> queryAllByUserId(Integer userId) {
        List<Exam> examList = new ArrayList<>();
        Group group = new Group();
        group.setUserId(userId);
        List<Group> groups = this.groupDao.queryAll(group);
        for (Group tempGroup : groups) {
            Exam exam ;
            if(tempGroup.getIsCommit()) {
                exam = this.examDao.queryById(tempGroup.getExamId());
                exam.setSubmitType("已提交");
            } else {
                exam = this.examDao.queryById(tempGroup.getExamId());
                exam.setSubmitType("未提交");
            }
            examList.add(exam);
        }

        return examList;
    }

}
